package org.duang.email;

import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.NullArgumentException;
import org.duang.common.exceptios.ServiceException;
import org.duang.config.Config;
import org.duang.kit.LogKit;
import org.duang.kit.ToolsKit;
import org.duang.logs.Logger;

import com.sun.mail.util.MailSSLSocketFactory;

public class EmailClient {

	private static Logger logger = LogKit.getLogger(EmailClient.class);
	private static java.util.concurrent.locks.ReentrantLock lock = new java.util.concurrent.locks.ReentrantLock();
	private static EmailClient client;
	private static MailSSLSocketFactory sf ;
	private static Properties deaultProps;
	private static MailSmtpConfig smtpConfig;
	/**是否启用身份验证**/
    private boolean isAuth = true;

	private EmailClient() {
		try {
			sf = new MailSSLSocketFactory();
			sf.setTrustAllHosts(true);  
			deaultProps = new Properties();
			deaultProps.setProperty(MailSmtpConfig.SMTP_AUTH,  "true");
			deaultProps.setProperty(MailSmtpConfig.TRANSPORT_PROTOCOL, "auth");
			deaultProps.setProperty(MailSmtpConfig.SMTP_STARTTLS_ENABLE, "true");
			deaultProps.put(MailSmtpConfig.SMTP_SSL_ENABLE, "true");  
			deaultProps.put(MailSmtpConfig.SMTP_SSL_SOCKET_FCTORY, sf);
			deaultProps.setProperty(MailSmtpConfig.SMTP_HOST, getMailSmtpConfig().getSmtp());
			deaultProps.setProperty(MailSmtpConfig.SMTP_PORT, getMailSmtpConfig().getPort() + "");
		} catch (Exception e) {
			e.printStackTrace();
			logger.print(e.getMessage(), e);
		}  
	}

	public static EmailClient duang() {
		synchronized (lock) {
			if (null == client) {
				client = new EmailClient();
			}
		}
		return client;
	}
	
	public static EmailClient init() {
		return new EmailClient();
	}

	public void setSmtpConfig(MailSmtpConfig config) {
		smtpConfig = config;
	}
	
	private Properties getSmtpProper() throws Exception {
		Properties props = getMailSmtpConfig().getProps();
		return (ToolsKit.isEmpty(props)) ? deaultProps : props;
	}
	
	private Authentication getAuth(String account, String password) throws Exception{
		if(ToolsKit.isEmpty(account) || ToolsKit.isEmpty(password)) {
			throw new NullArgumentException("account or password is null!");
		}
		Authentication auth = null;
		if (ToolsKit.isNotEmpty(account) && ToolsKit.isNotEmpty(password)) {
			auth = new Authentication(account, password);
		}
		return auth;
	}

	public boolean sendTextMail(String account, String password, String subject, String content, Set<String> receivers) {
		try {
			 // 根据邮件会话属性和密码验证器构造一个发送邮件的session
	        Session session = Session.getDefaultInstance(getSmtpProper(), getAuth(account, password));
	        Transport.send( this.makeMail(session, subject, content, account, receivers, false));
            return true;
        } catch (MessagingException e) {
        	e.printStackTrace();
        	logger.print(e.getMessage(), e);
        	throw new ServiceException(e.getMessage(), e);
        } catch (Exception e){
        	e.printStackTrace();
        	logger.print(e.getMessage(), e);
        	throw new ServiceException(e.getMessage(), e);
        }
	}

	private static MailSmtpConfig getMailSmtpConfig() throws Exception{
		if (ToolsKit.isEmpty(smtpConfig)) {
			smtpConfig = new MailSmtpConfig(Config.getEmailSmtp(), Config.getEmailSmtpProt());
		}
		return smtpConfig;
	}
	
	
	
	public boolean sendHtmlMail(String account, String password, String subject, String content, Set<String> receivers) {
		try {
			 // 根据邮件会话属性和密码验证器构造一个发送邮件的session
	        Session session = Session.getDefaultInstance(getSmtpProper(), getAuth(account, password));
	        Transport.send( this.makeMail(session, subject, content, account, receivers, true));
            return true;
        } catch (MessagingException e) {
        	e.printStackTrace();
        	logger.print(e.getMessage(), e);
        	throw new ServiceException(e.getMessage(), e);
        } catch (Exception e){
        	e.printStackTrace();
        	logger.print(e.getMessage(), e);
        	throw new ServiceException(e.getMessage(), e);
        }
	}
	
	 /**
     * 创建邮件message
     *
     * @param session       根据配置获得的session
     * @param title         邮件主题
     * @param content       邮件的内容
     * @param from          发件者
     * @param receivers     收件者
     * @param isHtmlMail    是否是html邮件
     */
    private Message makeMail(Session session, String subject, String content, String from, Set<String> receivers, boolean isHtmlMail){
        Message message = new MimeMessage(session);
        try {
            /**标题**/
            message.setSubject(subject);
            /**内容**/
            if(isHtmlMail){
                //是html邮件
                message.setContent(content, "text/html;charset=utf-8");
            } else {
                //普通邮件
                message.setText(content);
            }
            /**发件者地址**/
            Address fromAddress = new InternetAddress(from);
            message.setFrom(fromAddress);
            /**接收者地址**/
            Address[] tos = new InternetAddress[receivers.size()];
            int i = 0;
            for(Iterator<String> it = receivers.iterator(); it.hasNext();) {
                String receiver = it.next();
                if(isEmail(receiver)){
                    tos[i++] = new InternetAddress(receiver);
                }
            }
            /**发件时间**/
            message.setSentDate(new Date());

            message.setRecipients(Message.RecipientType.TO, tos);
        } catch (MessagingException e) {
            e.printStackTrace();
            logger.print(e.getMessage(), e);
            throw new ServiceException(e.getMessage(), e);
        } catch (Exception e) {
            e.printStackTrace();
            logger.print(e.getMessage(), e);
            throw new ServiceException(e.getMessage(), e);
        }
        return message;
    }

    public boolean isEmail(String address) {
    	return true;
    }
    
	public boolean isAuth() {
        return isAuth;
    }

    public void setAuth(boolean auth) {
        isAuth = auth;
    }
}
